////////////////////////////////////////////////////////////////////////////////////////
//
// JSimpleSim - A machine language simulator based on SimpSim by Anne-Gert Bultena.
//
// Copyright (C) 2008 Gerardo Camorlinga, Ryan Fitzgerald, and RJ Gordon
//
// This file is part of JSimpleSim.
//
// JSimpleSim is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// JSimpleSim is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with JSimpleSim.  If not, see <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////////////

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jsimplesim.view.components;

import jsimplesim.view.*;
import jsimplesim.view.renderers.HighlightCellRenderer;
import jsimplesim.view.renderers.MemRedCellRenderer;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;

import org.apache.log4j.Logger;

import jsimplesim.model.MemHexTableModel;

/**
 * 
 * @author f08maroon
 */
@SuppressWarnings("serial")
public class HexTable extends JTable implements TableModelListener {
	int lastCol = -1;
	private TableColumn column;
	@SuppressWarnings("unused")
	private JSimpleSimView view;
	static Logger logger = Logger.getLogger(HexTable.class);

	/**
	 * 
	 * @param model
	 * @param view1
	 */
	public HexTable(MemHexTableModel model, JSimpleSimView view1) {
		super(model);
		this.view = view1;

		setFont(new Font("monospaced", Font.PLAIN, 12));
		setShowGrid(true);
		this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		setRowSelectionAllowed(false);
		setIntercellSpacing(new Dimension(0, 0));
		setBorder(javax.swing.BorderFactory
				.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));
		setAutoscrolls(false);

		setColumnSelectionAllowed(false);

		setName("memoryTable"); // NOI18N

		setRowHeight(19);

		getTableHeader().setReorderingAllowed(false);
		this.setCellSelectionEnabled(true);

		// Set the size of each column

		int characterWidth = getFontMetrics(getFont()).charWidth('w');
		int columns = getModel().getColumnCount();

		this.getModel().addTableModelListener(this);

		for (int i = 0; i < columns; i++) {
			column = getColumnModel().getColumn(i);

			if (i == 0) {
				column.setPreferredWidth(9 * characterWidth);
			} else {
				column.setPreferredWidth(3 * characterWidth);
			}
		}
		// disallow column resizing
		for (int i = 0; i <= 16; i++) {
			column = getColumnModel().getColumn(i);
			column.setResizable(false);
		}
		
		// Create column specific cell renderer

		HighlightCellRenderer highlightCellRenderer = new HighlightCellRenderer();

		column = getColumnModel().getColumn(0);
		column.setCellRenderer(highlightCellRenderer);

		// Set default cell editor

		HexCellEditor hce = new HexCellEditor();
		hce.setFont(getFont());
		DefaultCellEditor dce = new DefaultCellEditor(hce);
		dce.setClickCountToStart(1);
		setDefaultEditor(String.class, dce);

	}


	@Override
	protected void processKeyEvent(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_ENTER
				&& e.getID() == KeyEvent.KEY_PRESSED) {
			int getColumn = getSelectedColumn();
			int row = getSelectedRow();
			Rectangle r = getCellRect(row, getColumn, false);
			Point p = new Point(r.x, r.y);
			SwingUtilities.convertPointToScreen(p, this);

			try {
				Robot robot = new Robot();
				robot.mouseMove(p.x, p.y);
				robot.mousePress(InputEvent.BUTTON1_MASK);
				robot.mouseRelease(InputEvent.BUTTON1_MASK);
				robot.mousePress(InputEvent.BUTTON1_MASK);
				robot.mouseRelease(InputEvent.BUTTON1_MASK);
				robot.mouseMove(0, 0);
			} catch (Exception e2) {
			}
		} else {
			super.processKeyEvent(e);
		}

	}

	/*
	 * Control which columns can be selected
	 */
	@Override
	public void changeSelection(int row, int column, boolean toggle,
			boolean extend) {
		logger.debug("changeSelection row = " + row + " column = " + column);
		if (getValueAt(row, column) != null) {

			if (column == 0) {
				if (lastCol == 1) {
					if (row == 0) {
						row = 15;
						column = 16;
						super.changeSelection(row, column, toggle, extend);
						lastCol = column;
					} else {
						row--;
						column = 16;
						super.changeSelection(row, column, toggle, extend);
						lastCol = column;
					}

				} else if (lastCol == 16) {
					column++;
					super.changeSelection(row, column, toggle, extend);
					lastCol = column;

				}
			}

			else {
				super.changeSelection(row, column, toggle, extend);
				lastCol = column;
			}
		}
	}

	// Implement KeyListener
	/*
	 * public void keyPressed(KeyEvent e) {
	 * 
	 * switch (e.getKeyCode()) { case KeyEvent.VK_RIGHT: e.consume();
	 * switchCell(1); break;
	 * 
	 * case KeyEvent.VK_LEFT: e.consume(); switchCell(-1); break;
	 * 
	 * case KeyEvent.VK_TAB: e.consume(); switchCell(1); break;
	 * 
	 * } }
	 */
	/**
	 * 
	 * @param e
	 */
	public void keyTyped(KeyEvent e) {
	}

	/**
	 * 
	 * @param e
	 */
	public void keyReleased(KeyEvent e) {
	}

	@SuppressWarnings("unused")
	private void switchCell(int direction) {
		if (isEditing()) {
			return;
		}
		int row = getSelectedRow();
		logger.debug("Row = " + row);
		int getColumn = getSelectedColumn();
		logger.debug("Column = " + getColumn);

		getColumn += direction;

		if (getColumn < 1) {
			if (row == 0) {
				return;
			} else if (row < 0) {
				row = 0;
			} else {
				getColumn = 16;
				row--;
			}
		}

		if (getColumn > 16) {
			if (row == getRowCount()) {
				return;
			} else {
				getColumn = 1;
				row++;
			}
		}

		changeSelection(row, getColumn, false, false);

	}

	@Override
	public void updateUI() {
		super.updateUI();
		int columnCount = getColumnCount();
		TableColumnModel columnModel = getColumnModel();
		for (int i = 1; i < columnCount; i++) {
			columnModel.getColumn(i).setCellRenderer(new MemRedCellRenderer());
		}
	}

	/*
	 * @Override public void tableChanged(TableModelEvent e) { int row =
	 * e.getFirstRow(); int column = e.getColumn(); TableModel model =
	 * (TableModel)e.getSource(); String columnName =
	 * model.getColumnName(column); Object data = model.getValueAt(row, column);
	 * 
	 * // Do something with the data... }
	 */
}
